"""
@File    ：ding_talk.py
@Author  ：ixiaodu
@Date    ：2025/8/14
@Desc    ：钉钉通知封装
"""

import base64
import hashlib
import hmac
import time
import urllib.parse
from typing import Any, Text
from dingtalkchatbot.chatbot import DingtalkChatbot, FeedLink, ActionCard
from test_cases.conftest import test_results
from utils import config


class DingTalkSendMsg:
    """ 发送钉钉通知 """
    def __init__(self):
        self.timeStamp = str(round(time.time() * 1000))

    def xiao_ding(self):
        sign = self.get_sign()
        # 从yaml文件中获取钉钉配置信息
        webhook = config['ding_talk']['webhook'] + "&timestamp=" + self.timeStamp + "&sign=" + sign
        return DingtalkChatbot(webhook)

    def get_sign(self) -> Text:
        """
        根据时间戳 + "sign" 生成密钥
        :return:
        """
        string_to_sign = f'{self.timeStamp}\n{config["ding_talk"]["secret"]}'.encode('utf-8')
        hmac_code = hmac.new(
            config["ding_talk"]["secret"].encode('utf-8'),
            string_to_sign,
            digestmod=hashlib.sha256).digest()

        sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
        return sign

    def send_text(
            self,
            msg: Text,
            mobiles=None
    ) -> None:
        """
        发送文本信息
        :param msg: 文本内容
        :param mobiles: 艾特用户电话
        :return:
        """
        if not mobiles:
            self.xiao_ding().send_text(msg=msg, is_at_all=True)
        else:
            if isinstance(mobiles, list):
                self.xiao_ding().send_text(msg=msg, at_mobiles=mobiles)
            else:
                raise TypeError("mobiles类型错误 不是list类型.")

    def send_link(
            self,
            title: Text,
            text: Text,
            message_url: Text,
            pic_url: Text
    ) -> None:
        """
        发送link通知
        :return:
        """
        self.xiao_ding().send_link(
                title=title,
                text=text,
                message_url=message_url,
                pic_url=pic_url
            )

    def send_markdown(
            self,
            title: Text,
            msg: Text,
            mobiles=None,
            is_at_all=False
    ) -> None:
        """

        :param is_at_all:
        :param mobiles:
        :param title:
        :param msg:
        markdown 格式
        """

        if mobiles is None:
            self.xiao_ding().send_markdown(title=title, text=msg, is_at_all=is_at_all)
        else:
            if isinstance(mobiles, list):
                self.xiao_ding().send_markdown(title=title, text=msg, at_mobiles=mobiles)
            else:
                raise TypeError("mobiles类型错误 不是list类型.")

    @staticmethod
    def feed_link(
            title: Text,
            message_url: Text,
            pic_url: Text
    ) -> Any:
        """ FeedLink 二次封装 """
        return FeedLink(
            title=title,
            message_url=message_url,
            pic_url=pic_url
        )
    def send_action_card(self, title, text, btn_titles, btn_urls) -> None:
        """发送 action_card """
        action_card = ActionCard(
            title= title,
            text= text,
            btn_orientation=0,
            btns=[
                {
                    "title": btn_titles,
                    "actionURL": btn_urls
                }
            ]
        )
        self.xiao_ding().send_action_card(action_card)

    def send_feed_link(self, *arg) -> None:
        """发送 feed_lik """

        self.xiao_ding().send_feed_card(list(arg))

    def send_ding_notification(self):
        """ 发送钉钉报告通知 """
        text = f"""
        测试环境：{config['env']}
        执行结果
        成  功  率: {test_results.get('pass_rate', 0)}%
        用例总数量：{test_results.get('run_case', 0)}                                    
        通过用例数：{test_results.get('pass_case', 0)}
        失败用例数：{test_results.get('fail_case', 0)}
        异常用例数：{test_results.get('error_case', 0)}
        跳过用例数：{test_results.get('skip_case', 0)}
        用例执行时长：{round(test_results.get('times', 0), 2)} s
        时间：{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
        非相关负责人员可忽略此消息。
        """

        DingTalkSendMsg().send_action_card(title='【UI自动化通知】', text=text, btn_titles='查看报告', btn_urls=config['allure_url'],)


if __name__ == '__main__':
    DingTalkSendMsg().send_ding_notification()
